
#define __REG32(x)          (*((volatile unsigned int *)(x)))

#define UART_DR(base)   __REG32(base + 0x00)
#define UART_FR(base)   __REG32(base + 0x18)
#define UART_CR(base)   __REG32(base + 0x30)
#define UART_IMSC(base) __REG32(base + 0x38)
#define UART_ICR(base)  __REG32(base + 0x44)

#define UARTFR_RXFE     0x10
#define UARTFR_TXFF     0x20
#define UARTIMSC_RXIM   0x10
#define UARTIMSC_TXIM   0x20
#define UARTICR_RXIC    0x10
#define UARTICR_TXIC    0x20

/* UART */
#define PL011_UART0_BASE    0x09000000
#define PL011_UART0_SIZE    0x00001000
#define PL011_UART0_IRQNUM  (32 + 1)

#define UART0_BASE PL011_UART0_BASE

/**
 * Use UART0 as debug uart
 * Set baud rate and characteristics (115200 8N1) and map to GPIO
 */
void uart_init()
{
    /* initialize UART0 */

    /* enable Rx and Tx of UART */
    UART_CR(UART0_BASE) = (1 << 0) | (1 << 8) | (1 << 9);
}

/**
 * Send a character
 */
void uart_send(unsigned int c) {
    while (UART_FR(UART0_BASE) & UARTFR_TXFF);
    UART_DR(UART0_BASE) = c;
}

/**
 * Receive a character
 */
char uart_getc() {
    int ch;
    ch = -1;
    
    while ((UART_FR(UART0_BASE) & UARTFR_RXFE) != 0);
    ch = UART_DR(UART0_BASE) & 0xff;
    
    return ch;
}

/**
 * Display a string
 */
void uart_puts(char *s) {
    while(*s) {
        /* convert newline to carrige return + newline */
        if(*s=='\n')
            uart_send('\r');
        uart_send(*s++);
    }
}
